package com.yang.design.structure.proxy.cglib;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Calendar;

/**
 * 代理类
 * 作用:扩展日志功能
 */
public class UserLogProxy implements MethodInterceptor {

    //目标类
    private Object target;


    //构造方法,目标类通过构造方法传进去
    public UserLogProxy(Object target) {
        this.target = target;
    }

    /**
     * 生成CGLIB动态代理类
     * @return 代理类对象
     */
    public Object getLogProxy(){
        //增强器类,用来创建动态代理类
        Enhancer enhancer = new Enhancer();

        //设置代理类的父类字节码对象，其实就是目标类的字节码对象
        //因为CGLIB是通过继承的方式生成代理类的
        enhancer.setSuperclass(target.getClass());

        //设置回调: 对于代理类上所有的方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦截
        //即需要上传实现了MethodInterceptor接口的对象。
        //public void setCallback(Callback callback) 方法参数是Callback
        //而MethodInterceptor extend Callback , UserLogProxy implements MethodInterceptor
        //根据多态,传this
        enhancer.setCallback(this);

        //创建动态代理对象并返回
        return enhancer.create();
    }

    /**
     * 实现回调方法
     * @param o 代理对象
     * @param method 目标对象中的方法Method实例
     * @param args 目标方法的接收参数
     * @param methodProxy 代理对象中的方法的Method实例
     * @return 目标方法的返回值
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        System.out.println(formatter.format(calendar.getTime()) + " [" +method.getName() + "] 查询用户信息...]");

        //反射执行父类的方法,即目标类的方法。返回值是目标类的方法的返回值
        Object result = methodProxy.invokeSuper(o, args);

        return result;
    }
}
